package com.kcwl.carrier.infrastructure.utils;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MethodUtil {

	/**
	 * List类型转换
	 *
	 * List<User> userList = new ArrayList<User>();
	 * List<UserBak> userbakList = ListTypeConvert(UserBak.class, userList);
	 *
	 * @param classObject
	 * @param listobject
	 * @return
	 */
	public static <E, T> List<E> ListTypeConvert(Class<E> classObject, List<T> listobject) {
		List<E> list = new ArrayList<E>();
		for (Object obj : listobject) {
			list.add(copyProperties(classObject, obj));
		}
		return list;
	}

	/**
	 * 将实体对象的属性转换成List
	 *
	 * @param insClass 实体对象
	 * @return
	 */
	public static <T> List<String> getPropList(Class<T> insClass){
		Field[] fields = insClass.getDeclaredFields();        //获取实体类的所有属性，返回Field数组
		List<String> list = new ArrayList<String>();
		for(Field field : fields){
//			System.out.println(field.getModifiers() + ":" + field.getName());
			if((field.getModifiers() & java.lang.reflect.Modifier.STATIC) != java.lang.reflect.Modifier.STATIC){
				list.add(field.getName());
			}
		}
		return list;
	}

	/**
	 * 将Map转换成实体对象
	 *
	 * @param map  Map数组
	 * @param t    实体对象
	 * @return
	 */
	public static <T> T mapToEntry(Map<String, Object> map , T t){
		Set<Entry<String, Object>> entrySet = map.entrySet();
		for(Entry<String, Object> entry : entrySet){
			invoteSet(t, entry.getKey(), entry.getValue());
		}
		return t;
	}

	/**
	 * 通过反射将一个对象的值赋值个另外一个对象（前提是对象中属性的名字相同）
	 *
	 * 标准工具类：
	 * 	BeanUtils.copyProperties(dest, orig);
	 * 	PropertyUtils.copyProperties(dest, orig);
	 *
	 * @param classObject   指定类型的Class对象
	 * @param nativeEntity  有值的本地实体对象
	 * @return 后对象赋值前对象:即后赋前(后付钱)
	 */
	public static <E> E copyProperties(Class<E> classObject, Object nativeEntity) {
		// 指定类型的Class对象中的所有方法
		Method[] methods = classObject.getDeclaredMethods();
		// 有值的本地实体对象中的所有方法
		Method[] nativeMethods = nativeEntity.getClass().getDeclaredMethods();
		E obj = null;
		try {
			obj = classObject.newInstance();
			Method method = null;
			for (int i = 0; i < methods.length; i++) {
				method = methods[i];
				// classObject中的方法名
				String mehtodName = method.getName();
				if (mehtodName.substring(0, 3).equals("set")) {
					for (Method nmethod : nativeMethods) {
						// nativeEntity中的方法名
						String nmehtodName = nmethod.getName();
						if (nmehtodName.substring(0, 3).equals("get")) {
							if (mehtodName.substring(3).equals(nmehtodName.substring(3))) {
								method.invoke(obj, nmethod.invoke(nativeEntity));
							}
						} else if(nmehtodName.substring(0, 2).equals("is")){
							// 处理boolean类型
							if (mehtodName.substring(3).equals(nmehtodName.substring(2))) {
								method.invoke(obj, nmethod.invoke(nativeEntity));
							}
						}

					}
				}

			}

			return obj;
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;

	}


	/**
	 * 给对象Object实例的某个属性propName赋值value
	 *
	 * @param ins       对象实例
	 * @param propName  属性名称
	 * @param value     属性值
	 * @return
	 */
	public static Object invoteSet(Object ins, String propName, Object value) {
		if (null == value) {
			return null;
		}

		String methodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
		Method[] methods = ins.getClass().getDeclaredMethods();

		for (Method method : methods) {
			if (methodName.equals(method.getName())) {
				Class<?>[] parameterTypes = method.getParameterTypes();
				Class<?> param = parameterTypes[0];
				try {
					//给实例ins类中的method赋值value
					//method.invoke(ins, new Object[] { SysUtil.parseInteger(value) };
					if (param.equals(String.class)) {
						return method.invoke(ins, SysUtil.parseString(value));
					}else if(param.equals(Double.class) || param.equals(double.class)){
						return method.invoke(ins, SysUtil.parseDouble(value));
					}else if(param.equals(Long.class) || param.equals(long.class)){
						return method.invoke(ins, SysUtil.parseLong(value));
					}else if(param.equals(Integer.class) || param.equals(int.class)){
						return method.invoke(ins, SysUtil.parseInteger(value));
					}else if(param.equals(Date.class) && String.class.equals(value.getClass())){
						String valueStr = SysUtil.toStr(value);
						Date date = null;
						if(match("^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9]$", valueStr)){
							date = new SimpleDateFormat("yyyy-MM-dd").parse(valueStr);
						}else if(match("^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9][ ][0-2][0-9][:][0-5][0-9]$", valueStr)){
							date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(valueStr);
						}else if(match("^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9][ ][0-2][0-9][:][0-5][0-9][:][0-5][0-9]$", valueStr)){
							date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(valueStr);
						}
						if(date != null){
							return method.invoke(ins, date);
						}else{
							System.out.println("字符串时间未解析 + " + valueStr);
						}
					}else{
						return method.invoke(ins, value);
					}
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
			}
		}
		return null;
	}

	/**
	 * 获取实例对象Object的某个属性propName值
	 *
	 * @param ins       实例对象
	 * @param propName  属性名称
	 * @return
	 */
	public static Object invoteGet(Object ins, String propName) {
		return invoteGet(ins, propName, Object.class);
	}

	@SuppressWarnings("unchecked")
	public static <T> T invoteGet(Object ins, String propName, Class<T> value) {
		if (null == value) {
			return null;
		}

		String methodName = "get" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
		String booleanMethodName;//boolean类型的方法名称
		if(propName.startsWith("is")){
			booleanMethodName = propName;
		}else{
			booleanMethodName = "is" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
		}
		Method[] methods = ins.getClass().getDeclaredMethods();

		for (Method method : methods) {
			if (method.getName().equals(methodName) || method.getName().equals(booleanMethodName)) {
				try {
					return (T) method.invoke(ins, new Object[] {});
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
			}
		}
		return null;
	}

	/**
	 * 调用对象实例中的某个方法
	 *
	 * @param owner      对象实例
	 * @param methodName 方法名称
	 * @param args       参数数组
	 * @param argsClass  方法参数数组对应的类型(Class数组)
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes"})
	public static Object invokeMethod(Object owner, String methodName, Object[] args, Class[] argsClass) throws Exception {
		Method method = owner.getClass().getMethod(methodName, argsClass);
		return method.invoke(owner, args);
	}

	/**
	 * 调用对象实例中的某个方法
	 *
	 * @param owner        对象实例
	 * @param methodName   方法名称
	 * @param args         方法参数
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes"})
	public static Object invokeMethod(Object owner, String methodName, Object... args) throws Exception {
//		Class ownerClass = Class.forName(className);
//		Object owner = ownerClass.newInstance();
		Class[] argsClass = new Class[args.length];
		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}
		Method method = owner.getClass().getMethod(methodName, argsClass);
		return method.invoke(owner, args);
	}


	@SuppressWarnings("rawtypes")
	/*
	public static void classReplaceNullToClass(Object objA,Object objB){
		Class classA = objA.getClass();
		Class classB = objB.getClass();
		Method[] methods = classA.getMethods();
		for(int i=0;i<methods.length;i++){
			if(methods[i].getName().indexOf("get")!=-1 && !methods[i].getName().equals("getClass")){
				try {
					Object value = methods[i].invoke(objA, null);
					if(value!=null){
						String fieldName =	methods[i].getName().substring(3);
						Field field = classA.getDeclaredField(fieldName.substring(0,1).toLowerCase().concat(fieldName.substring(1)));
						Method method = classB.getMethod("set"+fieldName, field.getType());
						method.invoke(objB, value);
					}
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				}
			}
		}
	}
	*/


	/*
	public static void classReplaceNullEmptyToClass(Object objA,Object objB){
		Class classA = objA.getClass();
		Class classB = objB.getClass();
		Method[] methods = classA.getMethods();
		for(int i=0;i<methods.length;i++){
			if(methods[i].getName().indexOf("get")!=-1 && !methods[i].getName().equals("getClass")){
				try {
					Object value = methods[i].invoke(objA, null);
					if(value!=null && value!=""){
						String fieldName =	methods[i].getName().substring(3);
						Field field = classA.getDeclaredField(fieldName.substring(0,1).toLowerCase().concat(fieldName.substring(1)));
						Method method = classB.getMethod("set"+fieldName, field.getType());
						method.invoke(objB, value);
					}
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
				}
			}
		}
	}
	*/

	/**
	 * 正则表达式匹配
	 *
	 * @param patternStr
	 * @param value
	 * @return
	 */
	public static boolean match(String patternStr,Object value){
//		String param = "[0-9]{4}-[0-9]{2}-[0-9]{2}";
		String valueStr = SysUtil.toStr(value);
		Pattern pattern = Pattern.compile(patternStr);
		Matcher matcher = pattern.matcher(valueStr);
		return matcher.find();
	}

	public static void main(String[] args) throws ParseException {
		String valueStr = "2014-12-22 10:13";
		Date date = null;
		if(match("^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9]$", valueStr)){
			date = new SimpleDateFormat("yyyy-MM-dd").parse(valueStr);
			System.out.println(date);
		}else if(match("^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9][ ][0-2][0-9][:][0-5][0-9]$", valueStr)){
			date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(valueStr);
		}
		System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date));
	}

}
